package org.convallaria.infrastruct.db.handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;

/**
 * 数据库字段自动填充处理器
 * 
 * 功能特性：
 * - 自动填充创建时间、更新时间
 * - 支持多种用户上下文获取方式
 * - 线程安全的用户信息获取
 * - 支持自定义默认值
 * 
 * @author gjh
 * @since 2024-09-22
 */
@Slf4j
public class DefaultDBFieldHandler implements MetaObjectHandler {

    private static final String DEFAULT_USER = "system";
    private static final String DEFAULT_ADMIN = "admin";
    
    @Override
    public void insertFill(MetaObject metaObject) {
        log.debug("开始插入填充...");
        
        // 填充时间字段
        this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
        this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
        
        // 填充用户字段
        String currentUser = getCurrentUserId();
        this.strictInsertFill(metaObject, "createBy", String.class, currentUser);
        this.strictInsertFill(metaObject, "updateBy", String.class, currentUser);
        
        // 填充其他默认字段
        fillDefaultValues(metaObject);
        
        log.debug("插入字段填充完成 - 用户: {}", currentUser);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.debug("开始更新填充...");
        
        // 填充更新时间和更新人
        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
        
        String currentUser = getCurrentUserId();
        this.strictUpdateFill(metaObject, "updateBy", String.class, currentUser);
        
        log.debug("更新字段填充完成 - 用户: {}", currentUser);
    }

    /**
     * 填充默认值字段
     */
    private void fillDefaultValues(MetaObject metaObject) {
        try {
            // 填充逻辑删除字段默认值
            if (metaObject.hasSetter("deleted") && metaObject.getValue("deleted") == null) {
                this.setFieldValByName("deleted", 0, metaObject);
            }
            
            // 填充乐观锁版本号默认值
            if (metaObject.hasSetter("version") && metaObject.getValue("version") == null) {
                this.setFieldValByName("version", 0L, metaObject);
            }
            
        } catch (Exception e) {
            log.warn("填充默认值时发生异常", e);
        }
    }

    /**
     * 获取当前用户ID
     * 支持多种用户上下文获取方式
     *
     * @return 用户ID
     */
    private String getCurrentUserId() {
        try {
            // 方式1: 尝试从自定义用户上下文提供者获取
            String userId = getFromUserContextProvider();
            if (StringUtils.hasText(userId)) {
                return userId;
            }
            
            // 方式2: 尝试从Spring Security获取用户信息
            userId = getFromSpringSecurityContext();
            if (StringUtils.hasText(userId)) {
                return userId;
            }
            
            // 方式3: 尝试从自定义用户上下文获取
            userId = getFromCustomUserContext();
            if (StringUtils.hasText(userId)) {
                return userId;
            }
            
            // 方式4: 尝试从HTTP请求头获取
            userId = getFromHttpHeaders();
            if (StringUtils.hasText(userId)) {
                return userId;
            }
            
            // 方式5: 尝试从线程本地变量获取
            userId = getFromThreadLocal();
            if (StringUtils.hasText(userId)) {
                return userId;
            }
            
        } catch (Exception e) {
            log.warn("获取当前用户ID时发生异常", e);
        }
        
        // 默认返回系统用户
        return getDefaultUser();
    }

    /**
     * 从Spring Security上下文获取用户信息
     */
    private String getFromSpringSecurityContext() {
        try {
            // 检查是否存在Spring Security
            Class.forName("org.springframework.security.core.context.SecurityContextHolder");
            
            // 使用反射调用，避免强依赖
            Class<?> securityContextHolder = Class.forName("org.springframework.security.core.context.SecurityContextHolder");
            Object context = securityContextHolder.getMethod("getContext").invoke(null);
            
            if (context != null) {
                Object authentication = context.getClass().getMethod("getAuthentication").invoke(context);
                if (authentication != null) {
                    Object principal = authentication.getClass().getMethod("getPrincipal").invoke(authentication);
                    if (principal != null) {
                        // 如果是UserDetails类型
                        try {
                            Object username = principal.getClass().getMethod("getUsername").invoke(principal);
                            return username != null ? username.toString() : null;
                        } catch (Exception e) {
                            // 如果不是UserDetails，直接返回toString
                            return principal.toString();
                        }
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            log.debug("Spring Security不可用，跳过Security上下文获取");
        } catch (Exception e) {
            log.debug("从Spring Security获取用户信息失败: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 从自定义用户上下文获取（可以根据项目需求实现）
     */
    private String getFromCustomUserContext() {
        try {
            // 这里可以实现项目特定的用户上下文获取逻辑
            // 例如：从自定义的UserContext工具类获取
            /*
            Class<?> userContextClass = Class.forName("org.convallaria.framework.security.UserContext");
            Object currentUser = userContextClass.getMethod("getCurrentUser").invoke(null);
            if (currentUser != null) {
                return currentUser.getClass().getMethod("getId").invoke(currentUser).toString();
            }
            */
        } catch (Exception e) {
            log.debug("从自定义用户上下文获取用户信息失败: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 从HTTP请求头获取用户信息
     */
    private String getFromHttpHeaders() {
        try {
            // 检查是否在Web环境中
            Class.forName("org.springframework.web.context.request.RequestContextHolder");
            
            Class<?> requestContextHolder = Class.forName("org.springframework.web.context.request.RequestContextHolder");
            Object requestAttributes = requestContextHolder.getMethod("getRequestAttributes").invoke(null);
            
            if (requestAttributes != null) {
                Object request = requestAttributes.getClass()
                    .getMethod("getRequest").invoke(requestAttributes);
                
                if (request != null) {
                    // 尝试从常见的用户头中获取
                    String[] userHeaders = {"X-User-Id", "X-User-Name", "X-Current-User", "User-Id"};
                    
                    for (String header : userHeaders) {
                        Object headerValue = request.getClass()
                            .getMethod("getHeader", String.class).invoke(request, header);
                        if (headerValue != null && StringUtils.hasText(headerValue.toString())) {
                            return headerValue.toString();
                        }
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            log.debug("Web环境不可用，跳过HTTP头获取");
        } catch (Exception e) {
            log.debug("从HTTP请求头获取用户信息失败: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 从线程本地变量获取用户信息
     */
    private String getFromThreadLocal() {
        try {
            // 这里可以实现从ThreadLocal获取用户信息的逻辑
            // 例如：UserThreadLocal.getCurrentUserId()
        } catch (Exception e) {
            log.debug("从ThreadLocal获取用户信息失败: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 获取默认用户
     * 可以根据不同环境返回不同的默认用户
     */
    private String getDefaultUser() {
        // 可以根据环境或配置返回不同的默认用户
        String activeProfile = getActiveProfile();
        
        if ("prod".equals(activeProfile) || "production".equals(activeProfile)) {
            return DEFAULT_USER;
        } else if ("test".equals(activeProfile)) {
            return "test-user";
        } else {
            return DEFAULT_ADMIN; // 开发环境使用admin
        }
    }

    /**
     * 获取当前激活的配置文件
     */
    private String getActiveProfile() {
        try {
            // 从系统属性获取
            String profiles = System.getProperty("spring.profiles.active");
            if (StringUtils.hasText(profiles)) {
                return profiles.split(",")[0].trim();
            }
            
            // 从环境变量获取
            profiles = System.getenv("SPRING_PROFILES_ACTIVE");
            if (StringUtils.hasText(profiles)) {
                return profiles.split(",")[0].trim();
            }
            
        } catch (Exception e) {
            log.debug("获取激活配置文件失败: {}", e.getMessage());
        }
        return "dev";
    }

    /**
     * 设置用户上下文提供者（可选的扩展方式）
     */
    public interface UserContextProvider {
        /**
         * 获取当前用户ID
         * @return 用户ID
         */
        String getCurrentUserId();
    }

    // 静态的用户上下文提供者，可以由外部设置
    private static volatile UserContextProvider userContextProvider;

    /**
     * 设置自定义的用户上下文提供者
     */
    public static void setUserContextProvider(UserContextProvider provider) {
        userContextProvider = provider;
    }

    /**
     * 获取自定义用户上下文提供者设置的用户ID
     */
    private String getFromUserContextProvider() {
        try {
            if (userContextProvider != null) {
                return userContextProvider.getCurrentUserId();
            }
        } catch (Exception e) {
            log.debug("从用户上下文提供者获取用户信息失败: {}", e.getMessage());
        }
        return null;
    }
}
